package com.attendance.config;

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {


    @Resource
    OVAuthenticationSuccessHandler authenticationSuccessHandler;

    @Resource
    OVAuthenticationFailureHandler authenticationFailureHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.headers(
                httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer
                        .contentSecurityPolicy(
                                contentSecurityPolicyConfig -> contentSecurityPolicyConfig
                                        .policyDirectives("default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:")
                        ).frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin // 防止点击劫持
                        )
                        .xssProtection(xss -> xss
                                .headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)
                        )
                        .httpStrictTransportSecurity(hsts -> hsts
                                .includeSubDomains(true)
                                .maxAgeInSeconds(31536000)
                        )
        );

        http.cors(Customizer.withDefaults()); // 支持跨域

        http.csrf(AbstractHttpConfigurer::disable); // 关闭csrf防御

        http.authorizeHttpRequests(
                authorize -> authorize
                        .requestMatchers("/api/user/add*", "/api/user/code*", "/api/user/session*", "/static/**", "/api/team/agree*", "/api/team/agreea*").permitAll()
                        .requestMatchers("/api/user/authentication", "/api/user/rename*", "/api/flag/**","/api/team/**").hasAnyAuthority("USER_ISAUTHENTICATION")
                        .anyRequest()
                        .authenticated()
        );

        // 登录配置
        http.formLogin(httpSecurityFormLoginConfigurer -> {
            httpSecurityFormLoginConfigurer
                    .loginPage("https://yuquanxi.site/login")
                    .loginProcessingUrl("/login").permitAll()
                    .usernameParameter("email") // 自定义表单参数
                    .passwordParameter("password") // 自定义表单参数
                    .successHandler(authenticationSuccessHandler)
                    .failureHandler(authenticationFailureHandler);
        });

        // 注销配置
        http.logout(httpSecurityLogoutConfigurer -> {
            httpSecurityLogoutConfigurer.logoutSuccessHandler(new OVLogoutSuccessHandler()); // 注销成功时的处理
            httpSecurityLogoutConfigurer.logoutUrl("/logout");
            httpSecurityLogoutConfigurer.logoutSuccessUrl("https://yuquanxi.site/login");
        });


        // 配置会话处理
        http.sessionManagement(httpSecuritySessionManagementConfigurer -> {
            httpSecuritySessionManagementConfigurer
                    .invalidSessionUrl("/api/user/session")
                    .maximumSessions(1)
                    .maxSessionsPreventsLogin(false)
                    .expiredSessionStrategy(new OVSessionInformationExpiredStrategy());

        });


        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return super.encode(rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return super.matches(rawPassword, encodedPassword);
            }
        };
    }

}
